<?php
/**
 * Created by PhpStorm.
 * User: chunyang
 * Date: 2018/4/11
 * Time: 16:08
 */

namespace Biz\module\Classes;

use Biz\model\settlement\BaseAccountTransaction;
use Biz\model\settlement\HhzCost as mHhzCost;
use Biz\model\settlement\HhzInCome as mHhzInCome;
use Biz\model\settlement\Settlement as mSettlement;
use Biz\model\settlement\SettlementAccount as mSettlementAccount;
use Biz\model\settlement\TransactionLog as mTransactionLog;
use Biz\model\settlement\WillSettlement as mWillSettlement;
use Doraemon\tools\Log as toolsLog;
use Biz\tools\OrderNo as toolsOrderNo;

class SettlementTransaction
{
    /**
     * 成功提交订单流程
     * @param $shopId 店铺id
     * @param $orderNo 订单no
     * @param $integralAmount 积分抵扣金额
     * @param $couponAmount 平台优惠券金额
     * @param $activityAllowance 平台活动补贴
     * @param $packetAmount 红包抵扣金额
     * @param $operateTime
     * @return bool
     * @throws \Exception
     */
    public function afterCreateOrder($shopId, $orderNo, $integralAmount, $couponAmount, $activityAllowance, $packetAmount, $operateTime)
    {
        $mHhzCost = mHhzCost::class;
        $mWillSettlement = mWillSettlement::class;
        $hhzConstData = [
            'shop_id' => $shopId,
            'order_no' => $orderNo,
            'transaction_type' => 0,
            'transaction_amount' => 0,
            'addtime' => $operateTime,
            'remark' => '',
        ];
        $willSettlementData = [
            'shop_id' => $shopId,
            'order_no' => $orderNo,
            'transaction_type' => 0,
            'transaction_amount' => 0,
            'addtime' => $operateTime,
            'remark' => '',
        ];
        $funArr = [];
        $transactionTypes = [];
        $accountTypes = [];
        if (floatval($integralAmount)) {//积分支付
            $transactionType = mHhzCost::TRANSACTION_TYPE_INTEGRAL_PAYMENT;

            $hhzConstData['transaction_type'] = $transactionType;
            $hhzConstData['transaction_amount'] = -floatval($integralAmount);
            $hhzConstData['remark'] = mHhzCost::$transactionTypeDesc[$transactionType];

            $funArr[] = ["$mHhzCost", "addData", $hhzConstData];

            $willSettlementData['transaction_type'] = $transactionType;
            $willSettlementData['transaction_amount'] = floatval($integralAmount);
            $willSettlementData['remark'] = mHhzCost::$transactionTypeDesc[$transactionType];

            $funArr[] = ["$mWillSettlement", "addData", $willSettlementData];
            $transactionTypes[] = $transactionType;
            $accountTypes[] = mWillSettlement::$actionClassToAccountType[$mHhzCost];
            $accountTypes[] = mWillSettlement::$actionClassToAccountType[$mWillSettlement];
        }
        if (floatval($couponAmount)) {//平台优惠券支付
            $transactionType = mHhzCost::TRANSACTION_TYPE_HHZ_COUPON_PAYMENT;

            $hhzConstData['transaction_type'] = $transactionType;
            $hhzConstData['transaction_amount'] = -floatval($couponAmount);
            $hhzConstData['remark'] = mHhzCost::$transactionTypeDesc[$transactionType];

            $funArr[] = ["$mHhzCost", "addData", $hhzConstData];

            $willSettlementData['transaction_type'] = $transactionType;
            $willSettlementData['transaction_amount'] = floatval($couponAmount);
            $willSettlementData['remark'] = mHhzCost::$transactionTypeDesc[$transactionType];

            $funArr[] = ["$mWillSettlement", "addData", $willSettlementData];
            $transactionTypes[] = $transactionType;
            $accountTypes[] = mWillSettlement::$actionClassToAccountType[$mHhzCost];
            $accountTypes[] = mWillSettlement::$actionClassToAccountType[$mWillSettlement];
        }
        if (floatval($activityAllowance)) {//平台活动补贴
            $transactionType = mHhzCost::TRANSACTION_TYPE_HHZ_ACTIVITY_ALLOWANCE_PAYMENT;

            $hhzConstData['transaction_type'] = $transactionType;
            $hhzConstData['transaction_amount'] = -floatval($activityAllowance);
            $hhzConstData['remark'] = mHhzCost::$transactionTypeDesc[$transactionType];

            $funArr[] = ["$mHhzCost", "addData", $hhzConstData];

            $willSettlementData['transaction_type'] = $transactionType;
            $willSettlementData['transaction_amount'] = floatval($activityAllowance);
            $willSettlementData['remark'] = mHhzCost::$transactionTypeDesc[$transactionType];

            $funArr[] = ["$mWillSettlement", "addData", $willSettlementData];
            $transactionTypes[] = $transactionType;
            $accountTypes[] = mWillSettlement::$actionClassToAccountType[$mHhzCost];
            $accountTypes[] = mWillSettlement::$actionClassToAccountType[$mWillSettlement];
        }
        if (floatval($packetAmount)) {//红包支付
            $transactionType = mHhzCost::TRANSACTION_TYPE_RED_PACKET_PAYMENT;

            $hhzConstData['transaction_type'] = $transactionType;
            $hhzConstData['transaction_amount'] = -floatval($packetAmount);
            $hhzConstData['remark'] = mHhzCost::$transactionTypeDesc[$transactionType];

            $funArr[] = ["$mHhzCost", "addData", $hhzConstData];

            $willSettlementData['transaction_type'] = $transactionType;
            $willSettlementData['transaction_amount'] = floatval($packetAmount);
            $willSettlementData['remark'] = mHhzCost::$transactionTypeDesc[$transactionType];

            $funArr[] = ["$mWillSettlement", "addData", $willSettlementData];
            $transactionTypes[] = $transactionType;
            $accountTypes[] = mWillSettlement::$actionClassToAccountType[$mHhzCost];
            $accountTypes[] = mWillSettlement::$actionClassToAccountType[$mWillSettlement];
        }
        if ($funArr) {
            $where = [
                'shop_id' => $shopId,
                'order_no' => $orderNo,
                'transaction_type' => array_unique($transactionTypes),
                'account_type' => array_unique($accountTypes),
                'status' => mTransactionLog::STATUS_NORMAL,
            ];
            if (mTransactionLog::hasLog($where)) {
                toolsLog::settlement_TransactionCreateOrder_warning('创建订单扣积分、优惠券、平台优惠券、红包流程已走，不能重复执行', [$shopId, $orderNo, $integralAmount, $couponAmount, $activityAllowance, $packetAmount, $operateTime]);
                throw new \Exception('创建订单扣积分或则优惠券或红包流程已走，不能重复执行');
            }
            $transactionFuns = $this->_formatTransactionFuns($funArr);
            return $this->updateTransaction($shopId, $orderNo, $transactionFuns);
        } else {
            return false;
        }
    }

    /**
     * 检查是否走成功提交订单流程
     * @param $shopId 店铺id
     * @param $orderNo 订单no
     * @param $integralAmount 积分抵扣金额
     * @param $couponAmount 平台优惠券金额
     * @param $activityAllowance 平台活动补贴
     * @param $packetAmount 红包抵扣金额
     * @return bool
     * @throws \Exception
     */
    public function checkAfterCreateOrder($shopId, $orderNo, $integralAmount, $couponAmount, $activityAllowance, $packetAmount)
    {
        $mHhzCost = mHhzCost::class;
        $mWillSettlement = mWillSettlement::class;
        $transactionTypes = [];
        $accountTypes = [];
        if (floatval($integralAmount)) {//积分支付
            $transactionType = mHhzCost::TRANSACTION_TYPE_INTEGRAL_PAYMENT;
            $transactionTypes[] = $transactionType;
            $accountTypes[] = mWillSettlement::$actionClassToAccountType[$mHhzCost];
            $accountTypes[] = mWillSettlement::$actionClassToAccountType[$mWillSettlement];
        }
        if (floatval($couponAmount)) {//平台优惠券支付
            $transactionType = mHhzCost::TRANSACTION_TYPE_HHZ_COUPON_PAYMENT;
            $transactionTypes[] = $transactionType;
            $accountTypes[] = mWillSettlement::$actionClassToAccountType[$mHhzCost];
            $accountTypes[] = mWillSettlement::$actionClassToAccountType[$mWillSettlement];
        }
        if (floatval($activityAllowance)) {//平台活动补贴
            $transactionType = mHhzCost::TRANSACTION_TYPE_HHZ_ACTIVITY_ALLOWANCE_PAYMENT;
            $transactionTypes[] = $transactionType;
            $accountTypes[] = mWillSettlement::$actionClassToAccountType[$mHhzCost];
            $accountTypes[] = mWillSettlement::$actionClassToAccountType[$mWillSettlement];
        }
        if (floatval($packetAmount)) {//现金红包支付
            $transactionType = mHhzCost::TRANSACTION_TYPE_RED_PACKET_PAYMENT;
            $transactionTypes[] = $transactionType;
            $accountTypes[] = mWillSettlement::$actionClassToAccountType[$mHhzCost];
            $accountTypes[] = mWillSettlement::$actionClassToAccountType[$mWillSettlement];
        }
        if ($transactionTypes && $accountTypes) {
            $where = [
                'shop_id' => $shopId,
                'order_no' => $orderNo,
                'transaction_type' => array_unique($transactionTypes),
                'account_type' => array_unique($accountTypes),
                'status' => mTransactionLog::STATUS_NORMAL,
            ];
            return mTransactionLog::hasLog($where);
        }
        return true;
    }

    /**
     * 取消订单成功
     * @param $shopId 店铺id
     * @param $orderNo 订单no
     * @param $integralAmount 积分抵扣金额或则
     * @param $couponAmount 平台优惠券金额
     * @param $activityAllowance 平台活动补贴
     * @param $packetAmount 红包抵扣金额
     * @param $operateTime
     * @return bool
     * @throws \Exception
     */
    public function afterCancelOrder($shopId, $orderNo, $integralAmount, $couponAmount, $activityAllowance, $packetAmount, $operateTime)
    {
        $mHhzCost = mHhzCost::class;
        $mWillSettlement = mWillSettlement::class;
        $hhzConstData = [
            'shop_id' => $shopId,
            'order_no' => $orderNo,
            'transaction_type' => 0,
            'transaction_amount' => 0,
            'addtime' => $operateTime,
            'remark' => '',
        ];
        $willSettlementData = [
            'shop_id' => $shopId,
            'order_no' => $orderNo,
            'transaction_type' => 0,
            'transaction_amount' => 0,
            'addtime' => $operateTime,
            'remark' => '',
        ];
        $funArr = [];
        $transactionTypes = [];
        $accountTypes = [];
        if (floatval($integralAmount)) { //退积分金额
            $transactionType = mHhzCost::TRANSACTION_TYPE_BACK_INTEGRAL;

            $willSettlementData['transaction_type'] = $transactionType;
            $willSettlementData['transaction_amount'] = -floatval($integralAmount);
            $willSettlementData['remark'] = mHhzCost::$transactionTypeDesc[$transactionType];

            $funArr[] = ["$mWillSettlement", "addData", $willSettlementData];

            $hhzConstData['transaction_type'] = $transactionType;
            $hhzConstData['transaction_amount'] = floatval($integralAmount);
            $hhzConstData['remark'] = mHhzCost::$transactionTypeDesc[$transactionType];

            $funArr[] = ["$mHhzCost", "addData", $hhzConstData];
            $transactionTypes[] = $transactionType;
            $accountTypes[] = mWillSettlement::$actionClassToAccountType[$mWillSettlement];
            $accountTypes[] = mWillSettlement::$actionClassToAccountType[$mHhzCost];
        }
        if (floatval($couponAmount)) {//退平台优惠券金额
            $transactionType = mHhzCost::TRANSACTION_TYPE_HHZ_BACK_COUPON;

            $willSettlementData['transaction_type'] = $transactionType;
            $willSettlementData['transaction_amount'] = -floatval($couponAmount);
            $willSettlementData['remark'] = mHhzCost::$transactionTypeDesc[$transactionType];

            $funArr[] = ["$mWillSettlement", "addData", $willSettlementData];

            $hhzConstData['transaction_type'] = $transactionType;
            $hhzConstData['transaction_amount'] = floatval($couponAmount);
            $hhzConstData['remark'] = mHhzCost::$transactionTypeDesc[$transactionType];

            $funArr[] = ["$mHhzCost", "addData", $hhzConstData];
            $transactionTypes[] = $transactionType;
            $accountTypes[] = mWillSettlement::$actionClassToAccountType[$mWillSettlement];
            $accountTypes[] = mWillSettlement::$actionClassToAccountType[$mHhzCost];
        }
        if (floatval($activityAllowance)) {//退平台活动补贴
            $transactionType = mHhzCost::TRANSACTION_TYPE_HHZ_BACK_ACTIVITY_ALLOWANCE;

            $willSettlementData['transaction_type'] = $transactionType;
            $willSettlementData['transaction_amount'] = -floatval($activityAllowance);
            $willSettlementData['remark'] = mHhzCost::$transactionTypeDesc[$transactionType];

            $funArr[] = ["$mWillSettlement", "addData", $willSettlementData];

            $hhzConstData['transaction_type'] = $transactionType;
            $hhzConstData['transaction_amount'] = floatval($activityAllowance);
            $hhzConstData['remark'] = mHhzCost::$transactionTypeDesc[$transactionType];

            $funArr[] = ["$mHhzCost", "addData", $hhzConstData];
            $transactionTypes[] = $transactionType;
            $accountTypes[] = mWillSettlement::$actionClassToAccountType[$mWillSettlement];
            $accountTypes[] = mWillSettlement::$actionClassToAccountType[$mHhzCost];
        }
        if (floatval($packetAmount)) { //退现金红包金额
            $transactionType = mHhzCost::TRANSACTION_TYPE_BACK_RED_PACKET;

            $willSettlementData['transaction_type'] = $transactionType;
            $willSettlementData['transaction_amount'] = -floatval($packetAmount);
            $willSettlementData['remark'] = mHhzCost::$transactionTypeDesc[$transactionType];

            $funArr[] = ["$mWillSettlement", "addData", $willSettlementData];

            $hhzConstData['transaction_type'] = $transactionType;
            $hhzConstData['transaction_amount'] = floatval($packetAmount);
            $hhzConstData['remark'] = mHhzCost::$transactionTypeDesc[$transactionType];

            $funArr[] = ["$mHhzCost", "addData", $hhzConstData];
            $transactionTypes[] = $transactionType;
            $accountTypes[] = mWillSettlement::$actionClassToAccountType[$mWillSettlement];
            $accountTypes[] = mWillSettlement::$actionClassToAccountType[$mHhzCost];
        }
        if ($funArr) {
            $where = [
                'shop_id' => $shopId,
                'order_no' => $orderNo,
                'transaction_type' => array_unique($transactionTypes),
                'account_type' => array_unique($accountTypes),
                'status' => mTransactionLog::STATUS_NORMAL,
            ];
            if (mTransactionLog::hasLog($where)) {
                toolsLog::settlement_TransactionCancelOrder_warning('取消订单退积分、退优惠券流程、退平台优惠券、退现金红包已走，不能重复执行', [$shopId, $orderNo, $integralAmount, $couponAmount, $activityAllowance, $packetAmount, $operateTime]);
                throw new \Exception('取消订单退积分或则退优惠券流程或退现金红包已走，不能重复执行');
            }
            $transactionFuns = $this->_formatTransactionFuns($funArr);
            return $this->updateTransaction($shopId, $orderNo, $transactionFuns);
        } else {
            return false;
        }
    }

    /**
     * 检查是否走取消订单成功流程
     * @param $shopId 店铺id
     * @param $orderNo 订单no
     * @param $integralAmount 积分抵扣金额或则
     * @param $couponAmount 平台优惠券金额
     * @param $activityAllowance 平台活动补贴
     * @param $packetAmount 红包抵扣金额
     * @return bool
     * @throws \Exception
     */
    public function checkAfterCancelOrder($shopId, $orderNo, $integralAmount, $couponAmount, $activityAllowance, $packetAmount)
    {
        $mHhzCost = mHhzCost::class;
        $mWillSettlement = mWillSettlement::class;
        $transactionTypes = [];
        $accountTypes = [];
        if (floatval($integralAmount)) { //退积分金额
            $transactionType = mHhzCost::TRANSACTION_TYPE_BACK_INTEGRAL;
            $transactionTypes[] = $transactionType;
            $accountTypes[] = mWillSettlement::$actionClassToAccountType[$mWillSettlement];
            $accountTypes[] = mWillSettlement::$actionClassToAccountType[$mHhzCost];
        }
        if (floatval($couponAmount)) {//退平台优惠券金额
            $transactionType = mHhzCost::TRANSACTION_TYPE_HHZ_BACK_COUPON;
            $transactionTypes[] = $transactionType;
            $accountTypes[] = mWillSettlement::$actionClassToAccountType[$mWillSettlement];
            $accountTypes[] = mWillSettlement::$actionClassToAccountType[$mHhzCost];
        }
        if (floatval($activityAllowance)) {//退平台活动补贴
            $transactionType = mHhzCost::TRANSACTION_TYPE_HHZ_BACK_ACTIVITY_ALLOWANCE;
            $transactionTypes[] = $transactionType;
            $accountTypes[] = mWillSettlement::$actionClassToAccountType[$mWillSettlement];
            $accountTypes[] = mWillSettlement::$actionClassToAccountType[$mHhzCost];
        }
        if (floatval($packetAmount)) {//退现金红包金额
            $transactionType = mHhzCost::TRANSACTION_TYPE_BACK_RED_PACKET;
            $transactionTypes[] = $transactionType;
            $accountTypes[] = mWillSettlement::$actionClassToAccountType[$mWillSettlement];
            $accountTypes[] = mWillSettlement::$actionClassToAccountType[$mHhzCost];
        }
        if ($transactionTypes && $accountTypes) {
            $where = [
                'shop_id' => $shopId,
                'order_no' => $orderNo,
                'transaction_type' => array_unique($transactionTypes),
                'account_type' => array_unique($accountTypes),
                'status' => mTransactionLog::STATUS_NORMAL,
            ];
            return mTransactionLog::hasLog($where);
        }
        return true;
    }

    /**
     *  订单支付成功
     * @param $shopId 店铺id
     * @param $orderNo 订单no
     * @param $transactionAmount 支付金额payamount
     * @param $operateTime 操作时间
     * @param string $payWay 支付方式
     * @param float $shippingAmount 运费
     * @return bool
     * @throws \Exception
     */
    public function afterPaySuccess($shopId, $orderNo, $transactionAmount, $operateTime, $payWay = '', $shippingAmount = 0.00)
    {
        $transactionType = BaseAccountTransaction::TRANSACTION_TYPE_USER_PAYMENT;
        $mWillSettlement = mWillSettlement::class;
        $willSettlementData = [
            'shop_id' => $shopId,
            'order_no' => $orderNo,
            'transaction_type' => $transactionType,
            'transaction_amount' => floatval($transactionAmount),
            'addtime' => $operateTime,
            'remark' => mHhzCost::$transactionTypeDesc[$transactionType],
            'pay_way' => $payWay,
            'shipping_amount' => $shippingAmount,
            'operate_type' => mSettlement::OPERATE_TYPE_USER,
            'operate_admin_id' => toolsOrderNo::getOrderUid($orderNo),
        ];
        $where = [
            'shop_id' => $shopId,
            'order_no' => $orderNo,
            'transaction_type' => $transactionType,
            'account_type' => mWillSettlement::$actionClassToAccountType[$mWillSettlement],
            'status' => mTransactionLog::STATUS_NORMAL,
        ];
        if (mTransactionLog::hasLog($where)) {
            toolsLog::settlement_TransactionOrderPaySuccess_warning('订单支付成功结算流程已走，不能重复执行', [$shopId, $orderNo, $transactionAmount, $operateTime, $payWay, $shippingAmount]);
            throw new \Exception('订单支付成功结算流程已走，不能重复执行');
        }
        $funArr[] = ["$mWillSettlement", "addData", $willSettlementData];
        $transactionFuns = $this->_formatTransactionFuns($funArr);
        return $this->updateTransaction($shopId, $orderNo, $transactionFuns);
    }

    /**
     *  检查是否走订单支付成功流程
     * @param $shopId 店铺id
     * @param $orderNo 订单no
     * @return bool
     * @throws \Exception
     */
    public function checkAfterPaySuccess($shopId, $orderNo)
    {
        $transactionType = BaseAccountTransaction::TRANSACTION_TYPE_USER_PAYMENT;
        $mWillSettlement = mWillSettlement::class;
        $where = [
            'shop_id' => $shopId,
            'order_no' => $orderNo,
            'transaction_type' => $transactionType,
            'account_type' => mWillSettlement::$actionClassToAccountType[$mWillSettlement],
            'status' => mTransactionLog::STATUS_NORMAL,
        ];
        return mTransactionLog::hasLog($where);
    }

    /**
     * 确认收货
     * @param $shopId 店铺id
     * @param $orderNo 订单no
     * @param $transactionAmount 订单交易实付金额payamount
     * @param $integralAmount 订单交易积分支付金额
     * @param $couponAmount 订单交易平台券支付金额
     * @param $activityAllowance 平台活动补贴
     * @param $packetAmount 红包抵扣金额
     * @param $commissions 订单佣金
     * @param $payWay 支付方式
     * @param $shippingAmount 运费
     * @param date $confirmTime 确认收货时间
     * @param bool $isSys 是否系统操作
     * @return bool
     * @throws \Exception
     */
    public function afterConfirmOrder($shopId, $orderNo, $transactionAmount, $integralAmount, $couponAmount, $activityAllowance, $packetAmount, $commissions, $payWay, $shippingAmount, $confirmTime, $isSys = false)
    {
        $confirmTime = ($confirmTime && strtotime($confirmTime)) ? $confirmTime : date('Y-m-d H:i:s');
        $mWillSettlement = mWillSettlement::class;
        $mSettlement = mSettlement::class;
        $mHhzInCome = mHhzInCome::class;

        $funArr = [];
        $transactionTypes = [];
        $accountTypes = [];

        $transactionType = BaseAccountTransaction::TRANSACTION_TYPE_ORDER_SETTLEMENT_RMB;
        $willSettlementData = [
            'shop_id' => $shopId,
            'order_no' => $orderNo,
            'transaction_type' => $transactionType,
            'transaction_amount' => -floatval($transactionAmount),
            'addtime' => $confirmTime,
            'remark' => mHhzCost::$transactionTypeDesc[$transactionType],
            'shipping_amount' => $shippingAmount,
            'operate_type' => $isSys ? mSettlement::OPERATE_TYPE_SYS : mSettlement::OPERATE_TYPE_USER,
            'operate_admin_id' => $isSys ? 0 : toolsOrderNo::getOrderUid($orderNo),
        ];
        $funArr[] = ["$mWillSettlement", "addData", $willSettlementData];
        $transactionTypes[] = $transactionType;
        $accountTypes[] = mSettlement::$actionClassToAccountType[$mWillSettlement];

        $settlementData = [
            'shop_id' => $shopId,
            'order_no' => $orderNo,
            'transaction_type' => $transactionType,
            'transaction_amount' => floatval($transactionAmount),
            'addtime' => $confirmTime,
            'remark' => mHhzCost::$transactionTypeDesc[$transactionType],
            'pay_way' => $payWay,
            'shipping_amount' => $shippingAmount,
            'operate_type' => $isSys ? mSettlement::OPERATE_TYPE_SYS : mSettlement::OPERATE_TYPE_USER,
            'operate_admin_id' => $isSys ? 0 : toolsOrderNo::getOrderUid($orderNo),
        ];
        $funArr[] = ["$mSettlement", "addData", $settlementData];
        $transactionTypes[] = $transactionType;
        $accountTypes[] = mSettlement::$actionClassToAccountType[$mSettlement];

        if ($integralAmount > 0) {
            $transactionType = mSettlement::TRANSACTION_TYPE_ORDER_SETTLEMENT_INTEGRAL;
            $willSettlementData = [
                'shop_id' => $shopId,
                'order_no' => $orderNo,
                'transaction_type' => $transactionType,
                'transaction_amount' => -floatval($integralAmount),
                'addtime' => $confirmTime,
                'remark' => mHhzCost::$transactionTypeDesc[$transactionType],
            ];
            $funArr[] = ["$mWillSettlement", "addData", $willSettlementData];
            $transactionTypes[] = $transactionType;
            $accountTypes[] = mSettlement::$actionClassToAccountType[$mWillSettlement];

            $settlementData = [
                'shop_id' => $shopId,
                'order_no' => $orderNo,
                'transaction_type' => $transactionType,
                'transaction_amount' => floatval($integralAmount),
                'addtime' => $confirmTime,
                'remark' => mHhzCost::$transactionTypeDesc[$transactionType],
                'pay_way' => $payWay,
            ];
            $funArr[] = ["$mSettlement", "addData", $settlementData];
            $transactionTypes[] = $transactionType;
            $accountTypes[] = mSettlement::$actionClassToAccountType[$mSettlement];
        }
        if ($couponAmount > 0) {
            $transactionType = mSettlement::TRANSACTION_TYPE_ORDER_SETTLEMENT_COUPON;
            $willSettlementData = [
                'shop_id' => $shopId,
                'order_no' => $orderNo,
                'transaction_type' => $transactionType,
                'transaction_amount' => -floatval($couponAmount),
                'addtime' => $confirmTime,
                'remark' => mHhzCost::$transactionTypeDesc[$transactionType],
            ];
            $funArr[] = ["$mWillSettlement", "addData", $willSettlementData];
            $transactionTypes[] = $transactionType;
            $accountTypes[] = mSettlement::$actionClassToAccountType[$mWillSettlement];

            $settlementData = [
                'shop_id' => $shopId,
                'order_no' => $orderNo,
                'transaction_type' => $transactionType,
                'transaction_amount' => floatval($couponAmount),
                'addtime' => $confirmTime,
                'remark' => mHhzCost::$transactionTypeDesc[$transactionType],
                'pay_way' => $payWay,
            ];
            $funArr[] = ["$mSettlement", "addData", $settlementData];
            $transactionTypes[] = $transactionType;
            $accountTypes[] = mSettlement::$actionClassToAccountType[$mSettlement];
        }
        if ($activityAllowance > 0) {
            $transactionType = mSettlement::TRANSACTION_TYPE_ORDER_SETTLEMENT_ACTIVITY_ALLOWANCE;
            $willSettlementData = [
                'shop_id' => $shopId,
                'order_no' => $orderNo,
                'transaction_type' => $transactionType,
                'transaction_amount' => -floatval($activityAllowance),
                'addtime' => $confirmTime,
                'remark' => mHhzCost::$transactionTypeDesc[$transactionType],
            ];
            $funArr[] = ["$mWillSettlement", "addData", $willSettlementData];
            $transactionTypes[] = $transactionType;
            $accountTypes[] = mSettlement::$actionClassToAccountType[$mWillSettlement];

            $settlementData = [
                'shop_id' => $shopId,
                'order_no' => $orderNo,
                'transaction_type' => $transactionType,
                'transaction_amount' => floatval($activityAllowance),
                'addtime' => $confirmTime,
                'remark' => mHhzCost::$transactionTypeDesc[$transactionType],
                'pay_way' => $payWay,
            ];
            $funArr[] = ["$mSettlement", "addData", $settlementData];
            $transactionTypes[] = $transactionType;
            $accountTypes[] = mSettlement::$actionClassToAccountType[$mSettlement];
        }
        if ($packetAmount > 0) {
            $transactionType = mSettlement::TRANSACTION_TYPE_ORDER_SETTLEMENT_RED_PACKET;
            $willSettlementData = [
                'shop_id' => $shopId,
                'order_no' => $orderNo,
                'transaction_type' => $transactionType,
                'transaction_amount' => -floatval($packetAmount),
                'addtime' => $confirmTime,
                'remark' => mHhzCost::$transactionTypeDesc[$transactionType],
            ];
            $funArr[] = ["$mWillSettlement", "addData", $willSettlementData];
            $transactionTypes[] = $transactionType;
            $accountTypes[] = mSettlement::$actionClassToAccountType[$mWillSettlement];

            $settlementData = [
                'shop_id' => $shopId,
                'order_no' => $orderNo,
                'transaction_type' => $transactionType,
                'transaction_amount' => floatval($packetAmount),
                'addtime' => $confirmTime,
                'remark' => mHhzCost::$transactionTypeDesc[$transactionType],
                'pay_way' => $payWay,
            ];
            $funArr[] = ["$mSettlement", "addData", $settlementData];
            $transactionTypes[] = $transactionType;
            $accountTypes[] = mSettlement::$actionClassToAccountType[$mSettlement];
        }
        if ($commissions > 0) {
            $transactionType = mSettlement::TRANSACTION_TYPE_DEDUCT_COMMISSION;
            $settlementData = [
                'shop_id' => $shopId,
                'order_no' => $orderNo,
                'transaction_type' => $transactionType,
                'transaction_amount' => -floatval($commissions),
                'addtime' => $confirmTime,
                'remark' => mHhzCost::$transactionTypeDesc[$transactionType],
                'pay_way' => $payWay
            ];
            $funArr[] = ["$mSettlement", "addData", $settlementData];
            $transactionTypes[] = $transactionType;
            $accountTypes[] = mSettlement::$actionClassToAccountType[$mSettlement];

            $mHhzInComeData = [
                'shop_id' => $shopId,
                'order_no' => $orderNo,
                'transaction_type' => $transactionType,
                'transaction_amount' => floatval($commissions),
                'addtime' => $confirmTime,
                'remark' => mHhzCost::$transactionTypeDesc[$transactionType],
            ];
            $funArr[] = ["$mHhzInCome", "addData", $mHhzInComeData];
            $transactionTypes[] = $transactionType;
            $accountTypes[] = mSettlement::$actionClassToAccountType[$mHhzInCome];
        } else {
            $commissions = 0;
        }

        $where = [
            'shop_id' => $shopId,
            'order_no' => $orderNo,
            'transaction_type' => array_unique($transactionTypes),
            'account_type' => array_unique($accountTypes),
            'status' => mTransactionLog::STATUS_NORMAL,
        ];
        if (mTransactionLog::hasLog($where)) {
            toolsLog::settlement_TransactionOrderPaySuccess_warning('确认收货结算流程已走，不能重复执行',
                [$shopId, $orderNo, $transactionAmount, $integralAmount, $couponAmount, $activityAllowance, $packetAmount, $commissions, $payWay, $shippingAmount, $confirmTime, $isSys]
            );
            throw new \Exception('确认收货结算流程已走，不能重复执行');
        }

        //更新结算账户余额
        $callBackArr = $this->_callbackUpdateSettlementBalance($shopId, $transactionAmount + $integralAmount + $couponAmount + $packetAmount + $activityAllowance - $commissions);
        $transactionFuns = $this->_formatTransactionFuns($funArr);
        return $this->updateTransaction($shopId, $orderNo, $transactionFuns, $callBackArr);
    }

    /**
     * 检查是否走确认收货流程
     * @param $shopId 店铺id
     * @param $orderNo 订单no
     * @param $integralAmount 订单交易积分支付金额
     * @param $couponAmount 订单交易平台券支付金额
     * @param $activityAllowance 平台活动补贴
     * @param $packetAmount 红包抵扣金额
     * @param $commissions 订单佣金
     * @return bool
     * @throws \Exception
     */
    public function checkAfterConfirmOrder($shopId, $orderNo, $integralAmount, $couponAmount, $activityAllowance, $packetAmount, $commissions)
    {
        $mWillSettlement = mWillSettlement::class;
        $mSettlement = mSettlement::class;
        $mHhzInCome = mHhzInCome::class;

        $transactionTypes = [];
        $accountTypes = [];

        $transactionType = BaseAccountTransaction::TRANSACTION_TYPE_ORDER_SETTLEMENT_RMB;
        $transactionTypes[] = $transactionType;
        $accountTypes[] = mSettlement::$actionClassToAccountType[$mSettlement];
        $accountTypes[] = mSettlement::$actionClassToAccountType[$mWillSettlement];

        if ($integralAmount > 0) {
            $transactionType = mSettlement::TRANSACTION_TYPE_ORDER_SETTLEMENT_INTEGRAL;
            $transactionTypes[] = $transactionType;
            $accountTypes[] = mSettlement::$actionClassToAccountType[$mWillSettlement];

            $transactionTypes[] = $transactionType;
            $accountTypes[] = mSettlement::$actionClassToAccountType[$mSettlement];
        }
        if ($couponAmount > 0) {
            $transactionType = mSettlement::TRANSACTION_TYPE_ORDER_SETTLEMENT_COUPON;
            $transactionTypes[] = $transactionType;
            $accountTypes[] = mSettlement::$actionClassToAccountType[$mWillSettlement];

            $transactionTypes[] = $transactionType;
            $accountTypes[] = mSettlement::$actionClassToAccountType[$mSettlement];
        }
        if ($activityAllowance > 0) {
            $transactionType = mSettlement::TRANSACTION_TYPE_ORDER_SETTLEMENT_ACTIVITY_ALLOWANCE;
            $transactionTypes[] = $transactionType;
            $accountTypes[] = mSettlement::$actionClassToAccountType[$mWillSettlement];

            $transactionTypes[] = $transactionType;
            $accountTypes[] = mSettlement::$actionClassToAccountType[$mSettlement];
        }
        if ($packetAmount > 0) {
            $transactionType = mSettlement::TRANSACTION_TYPE_ORDER_SETTLEMENT_RED_PACKET;
            $transactionTypes[] = $transactionType;
            $accountTypes[] = mSettlement::$actionClassToAccountType[$mWillSettlement];

            $transactionTypes[] = $transactionType;
            $accountTypes[] = mSettlement::$actionClassToAccountType[$mSettlement];
        }
        if ($commissions > 0) {
            $transactionType = mSettlement::TRANSACTION_TYPE_DEDUCT_COMMISSION;
            $transactionTypes[] = $transactionType;
            $accountTypes[] = mSettlement::$actionClassToAccountType[$mSettlement];

            $transactionTypes[] = $transactionType;
            $accountTypes[] = mSettlement::$actionClassToAccountType[$mHhzInCome];
        }

        $where = [
            'shop_id' => $shopId,
            'order_no' => $orderNo,
            'transaction_type' => array_unique($transactionTypes),
            'account_type' => array_unique($accountTypes),
            'status' => mTransactionLog::STATUS_NORMAL,
        ];

        return mTransactionLog::hasLog($where);
    }

    /**
     * 退款成功交易流程
     * @param $shopId
     * @param $orderNo
     * @param $refundOrderNo
     * @param int $type (1:确认收货前退款2:确认收货后退款)
     * @param $goodsId
     * @param $skuId
     * @param $goodsName 商品名称-sku名称
     * @param $transactionAmount 退款金额 支付金额payamount
     * @param $shippingAmount 退运费金额
     * @param $integralAmount 返积分金额
     * @param $couponAmount 返平台券金额
     * @param $activityAllowance 返平台活动补贴
     * @param $packetAmount 返红包抵扣金额
     * @param $confirmTime 确认退款成功时间
     * @param $payWay 支付方式
     * @param bool $isSys 是否系统操作
     * @param float|int $commissions 返佣金金额
     * @throws \Exception
     * @return bool
     */
    public function afterRefundSuccess($shopId, $orderNo, $refundOrderNo, $type = 1, $goodsId, $skuId, $goodsName, $transactionAmount, $shippingAmount, $integralAmount, $couponAmount, $activityAllowance, $packetAmount, $confirmTime, $payWay, $isSys = false, $commissions = 0)
    {
        $confirmTime = ($confirmTime && strtotime($confirmTime)) ? $confirmTime : date('Y-m-d H:i:s');
        $callBackArr = null;
        $mHhzCost = mHhzCost::class;
        $remark = '「' . $goodsName . '」退款';
        $transactionTypes = [];
        $accountTypes = [];
        $funArr = [];
        $transactionFuns = [];
        if ($type == 1) {//确认收货前退款 to 商家待结算
            $funArr = [];
            $mWillSettlement = mWillSettlement::class;
            //订单退款
            $transactionType = mSettlement::TRANSACTION_TYPE_ORDER_REFUND;
            $willSettlementData = [
                'shop_id' => $shopId,
                'order_no' => $orderNo,
                'goods_id' => $goodsId,
                'sku_id' => $skuId,
                'transaction_type' => $transactionType,
                'transaction_amount' => -floatval($transactionAmount),
                'addtime' => $confirmTime,
                'remark' => $remark,
                'shipping_amount' => $shippingAmount,
                'refund_order_no' => $refundOrderNo,
                'pay_way' => $payWay,
                'operate_type' => $isSys ? mSettlement::OPERATE_TYPE_SYS : mSettlement::OPERATE_TYPE_SHOP,
                'operate_admin_id' => $isSys ? 0 : $shopId,
            ];
            $funArr[] = ["$mWillSettlement", "addData", $willSettlementData];
            $transactionTypes[] = $transactionType;
            $accountTypes[] = mSettlement::$actionClassToAccountType[$mWillSettlement];

            if (floatval($integralAmount)) {
                //退款返积分
                $transactionType = mSettlement::TRANSACTION_TYPE_BACK_INTEGRAL;
                $willSettlementData = [
                    'shop_id' => $shopId,
                    'order_no' => $orderNo,
                    'goods_id' => $goodsId,
                    'sku_id' => $skuId,
                    'transaction_type' => $transactionType,
                    'transaction_amount' => -floatval($integralAmount),
                    'addtime' => $confirmTime,
                    'pay_way' => $payWay,
                    'refund_order_no' => $refundOrderNo,
                    'remark' => mHhzCost::$transactionTypeDesc[$transactionType],
                ];
                $hhzConstData = [
                    'shop_id' => $shopId,
                    'order_no' => $orderNo,
                    'goods_id' => $goodsId,
                    'sku_id' => $skuId,
                    'transaction_type' => $transactionType,
                    'transaction_amount' => floatval($integralAmount),
                    'addtime' => $confirmTime,
                    'refund_order_no' => $refundOrderNo,
                    'remark' => mHhzCost::$transactionTypeDesc[$transactionType],
                ];
                $funArr[] = ["$mWillSettlement", "addData", $willSettlementData];
                $funArr[] = ["$mHhzCost", "addData", $hhzConstData];
                $transactionTypes[] = $transactionType;
                $accountTypes[] = mSettlement::$actionClassToAccountType[$mWillSettlement];
                $accountTypes[] = mSettlement::$actionClassToAccountType[$mHhzCost];
            }
            if (floatval($couponAmount)) {
                //退款返券
                $transactionType = mSettlement::TRANSACTION_TYPE_HHZ_BACK_COUPON;
                $willSettlementData = [
                    'shop_id' => $shopId,
                    'order_no' => $orderNo,
                    'goods_id' => $goodsId,
                    'sku_id' => $skuId,
                    'transaction_type' => $transactionType,
                    'transaction_amount' => -floatval($couponAmount),
                    'pay_way' => $payWay,
                    'refund_order_no' => $refundOrderNo,
                    'addtime' => $confirmTime,
                    'remark' => mHhzCost::$transactionTypeDesc[$transactionType],
                ];
                $hhzConstData = [
                    'shop_id' => $shopId,
                    'order_no' => $orderNo,
                    'goods_id' => $goodsId,
                    'sku_id' => $skuId,
                    'transaction_type' => $transactionType,
                    'transaction_amount' => floatval($couponAmount),
                    'refund_order_no' => $refundOrderNo,
                    'addtime' => $confirmTime,
                    'remark' => mHhzCost::$transactionTypeDesc[$transactionType],
                ];
                $funArr[] = ["$mWillSettlement", "addData", $willSettlementData];
                $funArr[] = ["$mHhzCost", "addData", $hhzConstData];
                $transactionTypes[] = $transactionType;
                $accountTypes[] = mSettlement::$actionClassToAccountType[$mWillSettlement];
                $accountTypes[] = mSettlement::$actionClassToAccountType[$mHhzCost];
            }
            if (floatval($activityAllowance)) {
                //退款返活动补贴
                $transactionType = mSettlement::TRANSACTION_TYPE_HHZ_BACK_ACTIVITY_ALLOWANCE;
                $willSettlementData = [
                    'shop_id' => $shopId,
                    'order_no' => $orderNo,
                    'goods_id' => $goodsId,
                    'sku_id' => $skuId,
                    'transaction_type' => $transactionType,
                    'transaction_amount' => -floatval($activityAllowance),
                    'pay_way' => $payWay,
                    'refund_order_no' => $refundOrderNo,
                    'addtime' => $confirmTime,
                    'remark' => mHhzCost::$transactionTypeDesc[$transactionType],
                ];
                $hhzConstData = [
                    'shop_id' => $shopId,
                    'order_no' => $orderNo,
                    'goods_id' => $goodsId,
                    'sku_id' => $skuId,
                    'transaction_type' => $transactionType,
                    'transaction_amount' => floatval($activityAllowance),
                    'refund_order_no' => $refundOrderNo,
                    'addtime' => $confirmTime,
                    'remark' => mHhzCost::$transactionTypeDesc[$transactionType],
                ];
                $funArr[] = ["$mWillSettlement", "addData", $willSettlementData];
                $funArr[] = ["$mHhzCost", "addData", $hhzConstData];
                $transactionTypes[] = $transactionType;
                $accountTypes[] = mSettlement::$actionClassToAccountType[$mWillSettlement];
                $accountTypes[] = mSettlement::$actionClassToAccountType[$mHhzCost];
            }
            if (floatval($packetAmount)) {
                //退款返现金红包
                $transactionType = mSettlement::TRANSACTION_TYPE_BACK_RED_PACKET;
                $willSettlementData = [
                    'shop_id' => $shopId,
                    'order_no' => $orderNo,
                    'goods_id' => $goodsId,
                    'sku_id' => $skuId,
                    'transaction_type' => $transactionType,
                    'transaction_amount' => -floatval($packetAmount),
                    'addtime' => $confirmTime,
                    'pay_way' => $payWay,
                    'refund_order_no' => $refundOrderNo,
                    'remark' => mHhzCost::$transactionTypeDesc[$transactionType],
                ];
                $hhzConstData = [
                    'shop_id' => $shopId,
                    'order_no' => $orderNo,
                    'goods_id' => $goodsId,
                    'sku_id' => $skuId,
                    'transaction_type' => $transactionType,
                    'transaction_amount' => floatval($packetAmount),
                    'addtime' => $confirmTime,
                    'refund_order_no' => $refundOrderNo,
                    'remark' => mHhzCost::$transactionTypeDesc[$transactionType],
                ];
                $funArr[] = ["$mWillSettlement", "addData", $willSettlementData];
                $funArr[] = ["$mHhzCost", "addData", $hhzConstData];
                $transactionTypes[] = $transactionType;
                $accountTypes[] = mSettlement::$actionClassToAccountType[$mWillSettlement];
                $accountTypes[] = mSettlement::$actionClassToAccountType[$mHhzCost];
            }
            $transactionFuns = $this->_formatTransactionFuns($funArr);
        } else {
            if ($type == 2) {//确认收货后退款 to 商家结算 需要更新结算账户余额
                $funArr = [];
                $mSettlement = mSettlement::class;
                $mHhzInCome = mHhzInCome::class;
                //订单退款
                $transactionType = mSettlement::TRANSACTION_TYPE_ORDER_REFUND;
                $settlementData = [
                    'shop_id' => $shopId,
                    'order_no' => $orderNo,
                    'goods_id' => $goodsId,
                    'sku_id' => $skuId,
                    'transaction_type' => $transactionType,
                    'transaction_amount' => -floatval($transactionAmount),
                    'addtime' => $confirmTime,
                    'remark' => $remark,
                    'shipping_amount' => $shippingAmount,
                    'refund_order_no' => $refundOrderNo,
                    'pay_way' => $payWay,
                    'operate_type' => $isSys ? mSettlement::OPERATE_TYPE_SYS : mSettlement::OPERATE_TYPE_SHOP,
                    'operate_admin_id' => $isSys ? 0 : $shopId,
                ];
                $funArr[] = ["$mSettlement", "addData", $settlementData];
                $transactionTypes[] = $transactionType;
                $accountTypes[] = mSettlement::$actionClassToAccountType[$mSettlement];

                if (floatval($integralAmount)) {
                    //退款返积分
                    $transactionType = mSettlement::TRANSACTION_TYPE_BACK_INTEGRAL;
                    $settlementData = [
                        'shop_id' => $shopId,
                        'order_no' => $orderNo,
                        'goods_id' => $goodsId,
                        'sku_id' => $skuId,
                        'transaction_type' => $transactionType,
                        'transaction_amount' => -floatval($integralAmount),
                        'refund_order_no' => $refundOrderNo,
                        'addtime' => $confirmTime,
                        'remark' => mHhzCost::$transactionTypeDesc[$transactionType],
                        'pay_way' => $payWay
                    ];
                    $hhzConstData = [
                        'shop_id' => $shopId,
                        'order_no' => $orderNo,
                        'goods_id' => $goodsId,
                        'sku_id' => $skuId,
                        'transaction_type' => $transactionType,
                        'transaction_amount' => floatval($integralAmount),
                        'refund_order_no' => $refundOrderNo,
                        'addtime' => $confirmTime,
                        'remark' => mHhzCost::$transactionTypeDesc[$transactionType],
                    ];
                    $funArr[] = ["$mSettlement", "addData", $settlementData];
                    $funArr[] = ["$mHhzCost", "addData", $hhzConstData];
                    $transactionTypes[] = $transactionType;
                    $accountTypes[] = mSettlement::$actionClassToAccountType[$mSettlement];
                    $accountTypes[] = mSettlement::$actionClassToAccountType[$mHhzCost];
                }
                if (floatval($couponAmount)) {
                    //退款返券
                    $transactionType = mSettlement::TRANSACTION_TYPE_HHZ_BACK_COUPON;
                    $settlementData = [
                        'shop_id' => $shopId,
                        'order_no' => $orderNo,
                        'goods_id' => $goodsId,
                        'sku_id' => $skuId,
                        'transaction_type' => $transactionType,
                        'transaction_amount' => -floatval($couponAmount),
                        'addtime' => $confirmTime,
                        'remark' => mHhzCost::$transactionTypeDesc[$transactionType],
                        'pay_way' => $payWay,
                        'refund_order_no' => $refundOrderNo,
                    ];
                    $hhzConstData = [
                        'shop_id' => $shopId,
                        'order_no' => $orderNo,
                        'goods_id' => $goodsId,
                        'sku_id' => $skuId,
                        'transaction_type' => $transactionType,
                        'transaction_amount' => floatval($couponAmount),
                        'addtime' => $confirmTime,
                        'remark' => mHhzCost::$transactionTypeDesc[$transactionType],
                        'refund_order_no' => $refundOrderNo,
                    ];
                    $funArr[] = ["$mSettlement", "addData", $settlementData];
                    $funArr[] = ["$mHhzCost", "addData", $hhzConstData];
                    $transactionTypes[] = $transactionType;
                    $accountTypes[] = mSettlement::$actionClassToAccountType[$mSettlement];
                    $accountTypes[] = mSettlement::$actionClassToAccountType[$mHhzCost];
                }
                if (floatval($activityAllowance)) {
                    //退款返平台活动补贴
                    $transactionType = mSettlement::TRANSACTION_TYPE_HHZ_BACK_ACTIVITY_ALLOWANCE;
                    $settlementData = [
                        'shop_id' => $shopId,
                        'order_no' => $orderNo,
                        'goods_id' => $goodsId,
                        'sku_id' => $skuId,
                        'transaction_type' => $transactionType,
                        'transaction_amount' => -floatval($activityAllowance),
                        'addtime' => $confirmTime,
                        'remark' => mHhzCost::$transactionTypeDesc[$transactionType],
                        'pay_way' => $payWay,
                        'refund_order_no' => $refundOrderNo,
                    ];
                    $hhzConstData = [
                        'shop_id' => $shopId,
                        'order_no' => $orderNo,
                        'goods_id' => $goodsId,
                        'sku_id' => $skuId,
                        'transaction_type' => $transactionType,
                        'transaction_amount' => floatval($activityAllowance),
                        'addtime' => $confirmTime,
                        'remark' => mHhzCost::$transactionTypeDesc[$transactionType],
                        'refund_order_no' => $refundOrderNo,
                    ];
                    $funArr[] = ["$mSettlement", "addData", $settlementData];
                    $funArr[] = ["$mHhzCost", "addData", $hhzConstData];
                    $transactionTypes[] = $transactionType;
                    $accountTypes[] = mSettlement::$actionClassToAccountType[$mSettlement];
                    $accountTypes[] = mSettlement::$actionClassToAccountType[$mHhzCost];
                }
                if (floatval($packetAmount)) {
                    //退款返现金红包
                    $transactionType = mSettlement::TRANSACTION_TYPE_BACK_RED_PACKET;
                    $settlementData = [
                        'shop_id' => $shopId,
                        'order_no' => $orderNo,
                        'goods_id' => $goodsId,
                        'sku_id' => $skuId,
                        'transaction_type' => $transactionType,
                        'transaction_amount' => -floatval($packetAmount),
                        'refund_order_no' => $refundOrderNo,
                        'addtime' => $confirmTime,
                        'remark' => mHhzCost::$transactionTypeDesc[$transactionType],
                        'pay_way' => $payWay
                    ];
                    $hhzConstData = [
                        'shop_id' => $shopId,
                        'order_no' => $orderNo,
                        'goods_id' => $goodsId,
                        'sku_id' => $skuId,
                        'transaction_type' => $transactionType,
                        'transaction_amount' => floatval($packetAmount),
                        'refund_order_no' => $refundOrderNo,
                        'addtime' => $confirmTime,
                        'remark' => mHhzCost::$transactionTypeDesc[$transactionType],
                    ];
                    $funArr[] = ["$mSettlement", "addData", $settlementData];
                    $funArr[] = ["$mHhzCost", "addData", $hhzConstData];
                    $transactionTypes[] = $transactionType;
                    $accountTypes[] = mSettlement::$actionClassToAccountType[$mSettlement];
                    $accountTypes[] = mSettlement::$actionClassToAccountType[$mHhzCost];
                }
                //退款返佣金
                $transactionType = mSettlement::TRANSACTION_TYPE_BACK_COMMISSION;
                $mHhzInComeData = [
                    'shop_id' => $shopId,
                    'order_no' => $orderNo,
                    'goods_id' => $goodsId,
                    'sku_id' => $skuId,
                    'transaction_type' => $transactionType,
                    'transaction_amount' => -floatval($commissions),
                    'refund_order_no' => $refundOrderNo,
                    'addtime' => $confirmTime,
                    'remark' => mHhzCost::$transactionTypeDesc[$transactionType],
                ];
                $settlementData = [
                    'shop_id' => $shopId,
                    'order_no' => $orderNo,
                    'goods_id' => $goodsId,
                    'sku_id' => $skuId,
                    'transaction_type' => $transactionType,
                    'transaction_amount' => floatval($commissions),
                    'refund_order_no' => $refundOrderNo,
                    'addtime' => $confirmTime,
                    'remark' => mHhzCost::$transactionTypeDesc[$transactionType],
                    'pay_way' => $payWay
                ];
                $funArr[] = ["$mHhzInCome", "addData", $mHhzInComeData];
                $funArr[] = ["$mSettlement", "addData", $settlementData];
                $transactionTypes[] = $transactionType;
                $accountTypes[] = mSettlement::$actionClassToAccountType[$mHhzInCome];
                $accountTypes[] = mSettlement::$actionClassToAccountType[$mSettlement];

                $transactionFuns = $this->_formatTransactionFuns($funArr);
                //更新结算账户余额
                $callBackArr = $this->_callbackUpdateSettlementBalance($shopId, 0 - abs(floatval($transactionAmount)) - abs(floatval($integralAmount)) - abs(floatval($couponAmount)) - abs(floatval($activityAllowance)) - abs(floatval($packetAmount)) + floatval($commissions));
            }
        }
        if ($funArr) {
            $where = [
                'shop_id' => $shopId,
                'order_no' => $orderNo,
                'transaction_type' => array_unique($transactionTypes),
                'account_type' => array_unique($accountTypes),
                'status' => mTransactionLog::STATUS_NORMAL,
                'refund_order_no' => $refundOrderNo,
            ];
            if (mTransactionLog::hasLog($where)) {
                toolsLog::settlement_TransactionOrderRefund_warning('退款订单已经结算，不能重复结算',
                    [$shopId, $orderNo, $refundOrderNo, $type, $goodsId, $skuId, $goodsName, $transactionAmount, $shippingAmount, $integralAmount, $couponAmount, $activityAllowance, $packetAmount, $confirmTime, $payWay, $isSys, $commissions]
                );
                throw new \Exception('退款订单已经结算，不能重复结算');
            }

            return $this->updateTransaction($shopId, $orderNo, $transactionFuns, $callBackArr);
        } else {
            throw new \Exception('订单结算流程出错:参数错误');
        }
    }


    /**
     * 检查是否走退款成功交易流程
     * @param $shopId
     * @param $orderNo
     * @param $refundOrderNo
     * @param $integralAmount 返积分金额
     * @param $couponAmount 返平台券金额
     * @param $activityAllowance 返平台活动补贴
     * @param $packetAmount 返红包抵扣金额
     * @throws \Exception
     * @return bool
     */
    public function checkAfterRefundSuccess($shopId, $orderNo, $refundOrderNo, $integralAmount, $couponAmount, $activityAllowance, $packetAmount)
    {
        $mHhzCost = mHhzCost::class;
        $transactionTypes = [];
        $accountTypes = [];
        //确认收货前退款 to 商家待结算
        $mWillSettlement = mWillSettlement::class;
        //订单退款
        $transactionType = mSettlement::TRANSACTION_TYPE_ORDER_REFUND;
        $transactionTypes[] = $transactionType;
        $accountTypes[] = mSettlement::$actionClassToAccountType[$mWillSettlement];

        if (floatval($integralAmount)) {
            //退款返积分
            $transactionType = mSettlement::TRANSACTION_TYPE_BACK_INTEGRAL;
            $transactionTypes[] = $transactionType;
            $accountTypes[] = mSettlement::$actionClassToAccountType[$mWillSettlement];
            $accountTypes[] = mSettlement::$actionClassToAccountType[$mHhzCost];
        }
        if (floatval($couponAmount)) {
            //退款返券
            $transactionType = mSettlement::TRANSACTION_TYPE_HHZ_BACK_COUPON;
            $transactionTypes[] = $transactionType;
            $accountTypes[] = mSettlement::$actionClassToAccountType[$mWillSettlement];
            $accountTypes[] = mSettlement::$actionClassToAccountType[$mHhzCost];
        }
        if (floatval($activityAllowance)) {
            //退款返活动补贴
            $transactionType = mSettlement::TRANSACTION_TYPE_HHZ_BACK_ACTIVITY_ALLOWANCE;
            $transactionTypes[] = $transactionType;
            $accountTypes[] = mSettlement::$actionClassToAccountType[$mWillSettlement];
            $accountTypes[] = mSettlement::$actionClassToAccountType[$mHhzCost];
        }
        if (floatval($packetAmount)) {
            //退款返现金红包
            $transactionType = mSettlement::TRANSACTION_TYPE_BACK_RED_PACKET;
            $transactionTypes[] = $transactionType;
            $accountTypes[] = mSettlement::$actionClassToAccountType[$mWillSettlement];
            $accountTypes[] = mSettlement::$actionClassToAccountType[$mHhzCost];
        }
        $where = [
            'shop_id' => $shopId,
            'order_no' => $orderNo,
            'transaction_type' => array_unique($transactionTypes),
            'account_type' => array_unique($accountTypes),
            'status' => mTransactionLog::STATUS_NORMAL,
            'refund_order_no' => $refundOrderNo,
        ];
        //如果没有确认收获前的退款结算流程
        //则 检查是否有确认收货后的结算流程
        if (!mTransactionLog::hasLog($where)) {
            $transactionTypes = [];
            $accountTypes = [];
            //确认收货后退款 to 商家结算 需要更新结算账户余额
            $mSettlement = mSettlement::class;
            $mHhzInCome = mHhzInCome::class;
            //订单退款
            $transactionType = mSettlement::TRANSACTION_TYPE_ORDER_REFUND;
            $transactionTypes[] = $transactionType;
            $accountTypes[] = mSettlement::$actionClassToAccountType[$mSettlement];

            if (floatval($integralAmount)) {
                //退款返积分
                $transactionType = mSettlement::TRANSACTION_TYPE_BACK_INTEGRAL;
                $transactionTypes[] = $transactionType;
                $accountTypes[] = mSettlement::$actionClassToAccountType[$mSettlement];
                $accountTypes[] = mSettlement::$actionClassToAccountType[$mHhzCost];
            }
            if (floatval($couponAmount)) {
                //退款返券
                $transactionType = mSettlement::TRANSACTION_TYPE_HHZ_BACK_COUPON;
                $transactionTypes[] = $transactionType;
                $accountTypes[] = mSettlement::$actionClassToAccountType[$mSettlement];
                $accountTypes[] = mSettlement::$actionClassToAccountType[$mHhzCost];
            }
            if (floatval($activityAllowance)) {
                //退款返平台活动补贴
                $transactionType = mSettlement::TRANSACTION_TYPE_HHZ_BACK_ACTIVITY_ALLOWANCE;
                $transactionTypes[] = $transactionType;
                $accountTypes[] = mSettlement::$actionClassToAccountType[$mSettlement];
                $accountTypes[] = mSettlement::$actionClassToAccountType[$mHhzCost];
            }
            if (floatval($packetAmount)) {
                //退款返现金红包
                $transactionType = mSettlement::TRANSACTION_TYPE_BACK_RED_PACKET;
                $transactionTypes[] = $transactionType;
                $accountTypes[] = mSettlement::$actionClassToAccountType[$mSettlement];
                $accountTypes[] = mSettlement::$actionClassToAccountType[$mHhzCost];
            }
            //退款返佣金
            $transactionType = mSettlement::TRANSACTION_TYPE_BACK_COMMISSION;
            $transactionTypes[] = $transactionType;
            $accountTypes[] = mSettlement::$actionClassToAccountType[$mHhzInCome];
            $accountTypes[] = mSettlement::$actionClassToAccountType[$mSettlement];
            $where = [
                'shop_id' => $shopId,
                'order_no' => $orderNo,
                'transaction_type' => array_unique($transactionTypes),
                'account_type' => array_unique($accountTypes),
                'status' => mTransactionLog::STATUS_NORMAL,
                'refund_order_no' => $refundOrderNo,
            ];
            return mTransactionLog::hasLog($where);
        }
        return true;
    }


    /**
     * 提现成功后结算流程
     * @param $shopId
     * @param $transactionAmount 订单提现的金额
     * @param $transNumber 银行交易流水号
     * @param $operateTime 操作时间
     * @param $operateAdminId 操作人id
     * @param $remark 备注
     * @return bool
     * @throws \Exception
     */
    public function afterWithdrawal($shopId, $transactionAmount, $transNumber, $operateTime, $operateAdminId, $remark)
    {
        $operateTime = $operateTime ? $operateTime : date('Y-m-d H:i:s');
        $transactionType = mSettlement::TRANSACTION_TYPE_WITHDRAWAL;
        $mSettlement = mSettlement::class;
        $settlementData = [
            'shop_id' => $shopId,
            'order_no' => '',
            'transaction_type' => $transactionType,
            'transaction_amount' => -floatval($transactionAmount),
            'addtime' => $operateTime,
            'remark' => $remark,
            'operate_type' => mSettlement::OPERATE_TYPE_ADMIN,
            'operate_admin_id' => $operateAdminId,
            'bill_trans_number' => $transNumber,
        ];
        $funArr[] = ["$mSettlement", "addData", $settlementData];
        //更新结算账户余额
        $callBackArr = $this->_callbackUpdateSettlementBalance($shopId, 0 - abs($transactionAmount), true);
        $transactionFuns = $this->_formatTransactionFuns($funArr);
        return $this->updateTransaction($shopId, '', $transactionFuns, $callBackArr);
    }

    /**
     * 运营调整-调整佣金
     * @param int $shopId 店铺id
     * @param float $transactionAmount 调整金额
     * @param int $type （1 :补款 2：扣款）
     * @param $transNumber 银行交易流水号
     * @param $operateTime 操作时间
     * @param $operateAdminId
     * @param $remark
     * @return bool
     * @throws \Exception
     */
    public function businessAdjustment($shopId, $transactionAmount, $type = 1, $transNumber, $operateTime, $operateAdminId, $remark)
    {
        $operateTime = $operateTime ? $operateTime : date('Y-m-d H:i:s');
        $addTime = date('Y-m-d H:i:s');
        $transactionType = mSettlement::TRANSACTION_TYPE_COMMISSION_ADJUSTMENT;
        $transactionAmount = abs(floatval($transactionAmount));
        $mHhzIncome = mHhzInCome::class;
        $mSettlement = mSettlement::class;
        $hhzIncomeData = [
            'shop_id' => $shopId,
            'transaction_type' => $transactionType,
            'transaction_amount' => -$transactionAmount,
            'addtime' => $addTime,
            'operate_time' => $operateTime,
            'remark' => $remark,
            'operate_type' => mSettlement::OPERATE_TYPE_ADMIN,
            'operate_admin_id' => $operateAdminId,
            'bill_trans_number' => $transNumber,
        ];
        $settlementData = [
            'shop_id' => $shopId,
            'transaction_type' => $transactionType,
            'transaction_amount' => $transactionAmount,
            'addtime' => $addTime,
            'operate_time' => $operateTime,
            'remark' => $remark,
            'operate_type' => mSettlement::OPERATE_TYPE_ADMIN,
            'operate_admin_id' => $operateAdminId,
            'bill_trans_number' => $transNumber,
        ];
        $funArr = [];
        if ($type == 1) {//补款
            $hhzIncomeData['transaction_amount'] = -$transactionAmount;
            $settlementData['transaction_amount'] = $transactionAmount;

            $funArr = [];
            $funArr[] = ["$mHhzIncome", "addData", $hhzIncomeData];
            $funArr[] = ["$mSettlement", "addData", $settlementData];

            //更新结算账户余额
            $callBackArr = $this->_callbackUpdateSettlementBalance($shopId, abs($transactionAmount));
        } else if ($type == 2) {//扣款
            $settlementData['transaction_amount'] = -$transactionAmount;
            $hhzIncomeData['transaction_amount'] = $transactionAmount;

            $funArr = [];
            $funArr[] = ["$mSettlement", "addData", $settlementData];
            $funArr[] = ["$mHhzIncome", "addData", $hhzIncomeData];

            //更新结算账户余额
            $callBackArr = $this->_callbackUpdateSettlementBalance($shopId, 0 - abs($transactionAmount));
        }
        if ($funArr) {
            $transactionFuns = $this->_formatTransactionFuns($funArr);
            return $this->updateTransaction($shopId, '', $transactionFuns, $callBackArr);
        } else {
            throw new \Exception('运营调整-调整佣金结算流程出错:参数错误');
        }
    }

    /**
     * 运营调整-调整平台补贴
     * @param int $shopId 店铺id
     * @param float $transactionAmount 调整金额
     * @param int $type （1 :补款 2：扣款）
     * @param $transNumber 银行交易流水号
     * @param $operateTime 操作时间
     * @param $operateAdminId
     * @param $remark
     * @return bool
     * @throws \Exception
     */
    public function hhzAllowanceAdjustment($shopId, $transactionAmount, $type = 1, $transNumber, $operateTime, $operateAdminId, $remark)
    {
        $operateTime = $operateTime ? $operateTime : date('Y-m-d H:i:s');
        $addTime = date('Y-m-d H:i:s');
        $transactionType = mSettlement::TRANSACTION_TYPE_HHZ_ALLOWANCE_ADJUSTMENT;
        $transactionAmount = abs(floatval($transactionAmount));
        $mHhzCost = mHhzCost::class;
        $mSettlement = mSettlement::class;
        $hhzCostData = [
            'shop_id' => $shopId,
            'transaction_type' => $transactionType,
            'transaction_amount' => -$transactionAmount,
            'addtime' => $addTime,
            'operate_time' => $operateTime,
            'remark' => $remark,
            'operate_type' => mSettlement::OPERATE_TYPE_ADMIN,
            'operate_admin_id' => $operateAdminId,
            'bill_trans_number' => $transNumber,
        ];
        $settlementData = [
            'shop_id' => $shopId,
            'transaction_type' => $transactionType,
            'transaction_amount' => $transactionAmount,
            'addtime' => $addTime,
            'operate_time' => $operateTime,
            'remark' => $remark,
            'operate_type' => mSettlement::OPERATE_TYPE_ADMIN,
            'operate_admin_id' => $operateAdminId,
            'bill_trans_number' => $transNumber,
        ];
        $funArr = [];
        if ($type == 1) {//补款
            $hhzCostData['transaction_amount'] = -$transactionAmount;
            $settlementData['transaction_amount'] = $transactionAmount;

            $funArr = [];
            $funArr[] = ["$mHhzCost", "addData", $hhzCostData];
            $funArr[] = ["$mSettlement", "addData", $settlementData];

            //更新结算账户余额
            $callBackArr = $this->_callbackUpdateSettlementBalance($shopId, abs($transactionAmount));
        } else if ($type == 2) {//扣款
            $settlementData['transaction_amount'] = -$transactionAmount;
            $hhzCostData['transaction_amount'] = $transactionAmount;

            $funArr = [];
            $funArr[] = ["$mSettlement", "addData", $settlementData];
            $funArr[] = ["$mHhzCost", "addData", $hhzCostData];

            //更新结算账户余额
            $callBackArr = $this->_callbackUpdateSettlementBalance($shopId, 0 - abs($transactionAmount));
        }
        if ($funArr) {
            $transactionFuns = $this->_formatTransactionFuns($funArr);
            return $this->updateTransaction($shopId, '', $transactionFuns, $callBackArr);
        } else {
            throw new \Exception('运营调整-调整平台补贴结算流程出错:参数错误');
        }
    }


    /**
     * 保证金补货款（扣完保证金调用）
     * @param $shopId 店铺id
     * @param $transactionAmount 保证金补货款金额
     * @param $transNumber 银行交易流水号
     * @param $operateTime 操作时间
     * @param $operateAdminId
     * @param $remark
     * @throws
     * @return bool
     */
    public function depositAddGoodsAmount($shopId, $transactionAmount, $transNumber, $operateTime, $operateAdminId, $remark)
    {
        $transactionType = mSettlement::TRANSACTION_TYPE_DEPOSIT_ADD_GOODS_AMOUNT;
        $mSettlement = mSettlement::class;
        $depositData = [
            'shop_id' => $shopId,
            'transaction_type' => $transactionType,
            'transaction_amount' => -floatval($transactionAmount),
            'addtime' => $operateTime,
            'remark' => $remark,
            'operate_type' => mSettlement::OPERATE_TYPE_ADMIN,
            'operate_admin_id' => $operateAdminId,
            'bill_trans_number' => $transNumber,
        ];
        $funArr[] = ["", "", $depositData, BaseAccountTransaction::ACCOUNT_TYPE_SHOP_DEPOSIT];
        $settlementData = [
            'shop_id' => $shopId,
            'transaction_type' => $transactionType,
            'transaction_amount' => floatval($transactionAmount),
            'addtime' => $operateTime,
            'remark' => $remark,
            'operate_type' => mSettlement::OPERATE_TYPE_ADMIN,
            'operate_admin_id' => $operateAdminId,
            'bill_trans_number' => $transNumber,
        ];
        $funArr[] = ["$mSettlement", "addData", $settlementData];
        //更新结算账户余额
        $callBackArr = $this->_callbackUpdateSettlementBalance($shopId, abs($transactionAmount));
        $transactionFuns = $this->_formatTransactionFuns($funArr);
        return $this->updateTransaction($shopId, '', $transactionFuns, $callBackArr);
    }

    /**
     * 商家交保证金后结算流程 todo unit test 添加引用
     * @param $shopId
     * @param $transactionAmount
     * @param $transNumber 银行交易流水号
     * @param $operateTime
     * @throws
     * @return bool
     */
    public function addDeposit($shopId, $transactionAmount, $transNumber, $operateTime)
    {
        $transactionType = mSettlement::TRANSACTION_TYPE_ADD_DEPOSIT;
        $depositData = [
            'shop_id' => $shopId,
            'transaction_type' => $transactionType,
            'transaction_amount' => -floatval($transactionAmount),
            'addtime' => $operateTime,
            'remark' => mHhzCost::$transactionTypeDesc[$transactionType],
            'bill_trans_number' => $transNumber,
        ];
        $transactionFuns = $this->_formatTransactionFuns([["", "", $depositData, BaseAccountTransaction::ACCOUNT_TYPE_SHOP_DEPOSIT]]);
        return $this->updateTransaction($shopId, '', $transactionFuns);
    }

    /**
     * 关店退保成功后结算流程操作 todo unit test 添加引用
     * @param $shopId
     * @param $transactionAmount
     * @param $transNumber 银行交易流水号
     * @param $operateTime
     * @throws
     * @return bool
     */
    public function closeAndBackDeposit($shopId, $transactionAmount, $transNumber, $operateTime)
    {
        $transactionType = mSettlement::TRANSACTION_TYPE_CLOSE_BACK_DEPOSIT;
        $depositData = [
            'shop_id' => $shopId,
            'transaction_type' => $transactionType,
            'transaction_amount' => -floatval($transactionAmount),
            'addtime' => $operateTime,
            'remark' => mHhzCost::$transactionTypeDesc[$transactionType],
            'bill_trans_number' => $transNumber,
        ];
        $transactionFuns = $this->_formatTransactionFuns([["", "", $depositData, BaseAccountTransaction::ACCOUNT_TYPE_SHOP_DEPOSIT]]);
        return $this->updateTransaction($shopId, '', $transactionFuns);
    }


    /**
     * 更新交易流程数据
     * @param $shopId 店铺id
     * @param $orderNo 订单no
     * @param $transactionFuns 交易方法
     * @param $callBackArr 交易成功callback方法
     * @return bool
     * @throws
     */
    private function updateTransaction($shopId, $orderNo, $transactionFuns, $callBackArr = null)
    {
        $result = mTransactionLog::action(function () use ($shopId, $orderNo, $transactionFuns, $callBackArr) {
            foreach ($transactionFuns as $rows) {
                $fun = $rows[0];
                $params = $rows[1];
                $accountType = isset($params['account_type']) ? $params['account_type'] : 0;
                $logData = $params['data'];
                if (!isset($params['data']['addtime']) || strtotime($params['data']['addtime']) <= 0) {
                    $params['data']['addtime'] = date('Y-m-d H:i:s');
                }
                if (!isset($params['data']['operate_time'])) {
                    $params['data']['operate_time'] = $params['data']['addtime'];
                }
                $logData['account_type'] = $accountType;
                $logData['addtime'] = $params['data']['addtime'];
                $logData['operate_time'] = $params['data']['operate_time'];
                $logResult = mTransactionLog::addLog($logData);
                if ($logResult) {
                    if ($fun) {
                        call_user_func_array($fun, $params);
                    }
                } else {
                    return false;
                }
            }
            if (!is_null($callBackArr)) {
                $callBackFun = $callBackArr[0];
                $callBackParams = $callBackArr[1];
                call_user_func_array($callBackFun, $callBackParams);
            }
            return true;
        });
        if (!$result) {//如果交易流程出错。添加交易流程log日志
            toolsLog::settlement_transaction_warning('结算流程出错', [
                'shopId' => $shopId,
                'orderNo' => $orderNo,
                'transactionFuns' => $transactionFuns,
                'callBackArr' => $callBackArr,
            ]);
            throw new \Exception('结算流程出错');
        }
        return true;
    }

    private function _formatTransactionFuns($funsArr)
    {
        $result = [];
        foreach ($funsArr as $row) {
            $className = $row[0];
            $fun = $row[1];
            $params = $row[2];
            if ($className) {
                $accoutType = BaseAccountTransaction::$actionClassToAccountType[$className];
            } else {
                $accoutType = isset($row[3]) ? $row[3] : '';
            }
            $result[] = [
                ($className && $fun) ? [$className, $fun] : [],
                [
                    'data' => $params,
                    'account_type' => $accoutType
                ]
            ];
        }
        return $result;
    }

    /**
     * @param $shopId
     * @param $amount
     * @param bool $changeWithdrawalAmount 是否更改累计提现金额
     * @return array
     */
    private function _callbackUpdateSettlementBalance($shopId, $amount, $changeWithdrawalAmount = false)
    {
        $callBackFun = "actionUpdateSettlementBalance";
        $callBackArr = [
            [$this, "$callBackFun"],
            [$shopId, $amount, $changeWithdrawalAmount]
        ];
        return $callBackArr;
    }

    /**
     * 更新结算账户余额
     * 请在action方法中调用此方法
     * @param $shopId
     * @param $amount
     * @param bool $changeWithdrawalAmount 是否更改累计提现金额
     * @return bool
     * @throws \Exception
     */
    private function actionUpdateSettlementBalance($shopId, $amount, $changeWithdrawalAmount = false)
    {
        $result = mSettlementAccount::updateBalance($shopId, $amount, $changeWithdrawalAmount);
        if ($result) {
            return true;
        } else {
            toolsLog::settlement_UpdateSettlementBalance_warning('更新结算账户余额失败', [
                'shopId' => $shopId,
                'amount' => $amount,
                'changeWithdrawalAmount' => $changeWithdrawalAmount,
            ]);
            throw new \Exception('更新结算账户余额失败');
        }
    }
}